package com.antifly.common.utils;

import com.antifly.common.exception.bizException.BizException;
import com.antifly.common.pojo.dto.TreeNode;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * 生成树结构的工具类
 *
 * @author yangke
 * @date 2020-04-15
 */
public class TreeUtils {

    private TreeUtils() {
    }

    private static final Logger logger = LoggerFactory.getLogger(TreeUtils.class);

    /**
     * 生成树结构方法
     *
     * @param item   数据源
     * @param tClass 类型
     * @param <T>    泛型
     * @return
     */
    public static <T extends TreeNode> List<T> generateTreeList(List<? extends Map<String, Object>> item,
                                                                Class<T> tClass) {
        List<T> treeNodes = new ArrayList<>();
        try {
            Object object;
            // 定义 通过反射把map转成泛型对象
            Map<String, T> treeMap = new HashMap<>(item.size());
            List<T> dataTreeList = new ArrayList<>();
            for (Map<String, Object> pMap : item) {
                object = tClass.newInstance();
                String id = (String) pMap.get("id");
                if (StringUtils.isBlank(id)) {
                    throw new BizException("id数据不存在");
                }
                for (Map.Entry<String, Object> stringObjectEntry : pMap.entrySet()) {
                    // 默认的使用key作为类的属性名
                    Field field;
                    try {
                        // 通过key得到类的属性字段
                        field = tClass.getDeclaredField(stringObjectEntry.getKey());
                    } catch (Exception e) {
                        // 这里如果异常说明没有获取到，就去父类上面找，如果父类都没有就进行下一次
                        try {
                            Class<? super T> clazz = tClass.getSuperclass();
                            field = clazz.getDeclaredField(stringObjectEntry.getKey());
                        } catch (Exception e1) {
                            continue;
                        }
                    }
                    if (field == null) {
                        continue;
                    }
                    // 这里设置属性可以强制访问
                    field.setAccessible(true);
                    if (Objects.nonNull(stringObjectEntry.getValue())) {
                        if (stringObjectEntry.getValue() instanceof BigDecimal) {
                            field.set(object, Integer.parseInt(stringObjectEntry.getValue().toString()));
                        } else {
                            field.set(object, stringObjectEntry.getValue());
                        }
                    }
                }
                treeMap.put(id, (T) object);
                dataTreeList.add((T) object);
            }
            // 循环数据生成树结构，使用引用指向操作对象
            for (T dataTree : dataTreeList) {
                // 判断是否有子节点
                if (StringUtils.isBlank(dataTree.getParentId())) {
                    // 没有子节点
                    treeNodes.add(dataTree);
                } else {
                    // 根据父节点ID找到父节点
                    T parent = treeMap.get(dataTree.getParentId());
                    if (parent != null) {
                        // 将子节点放入父节点
                        parent.getChildren().add(dataTree);
                    } else {
                        treeNodes.add(dataTree);
                    }
                }
            }
        } catch (Exception e) {
            logger.info("树生成失败,{}", e.getMessage());
            e.printStackTrace();
        }
        return treeNodes;
    }
}
